home *** CD-ROM | disk | FTP | other *** search
/ Aminet 31 / Aminet 31 (1999)(Schatztruhe)[!][Jun 1999].iso / Aminet / dev / basic / UDP_Chat.lha / UDPChat / UDP_ChatV2.3.asc < prev    next >
Text File  |  1999-03-29  |  40KB  |  1,088 lines

  1. ;
  2. ;                      UDP Chat code V2.3   7/03/99
  3. ;
  4. ;    This code sends and receives UDP data packets like a
  5. ;  a simple IRC client, and  checks wether they have arrived
  6. ;  at their destination, and allows other copies of this
  7. ;  program to log in to this one (can act as a server or client).
  8. ;
  9. ;  Written by Anton Reinauer <anton@ww.co.nz>.
  10. ;  GUI: Alvaro Thompson <alvaro@enterprise.net> - And awful hacks
  11. ;  by me to his nice font sensitive code :-)
  12. ;        - typical bloody games programmer ;-)
  13. ;
  14. ;  Thanks to Paul Burkey for TCP_Funcs and to Dr. Ercole Spiteri
  15. ;  for TCP-to-Blitz.
  16. ;
  17. ;  ARexx portname: "UDP_Chat"
  18. ;
  19. ;  Turn overflow errors off in Debugger options,
  20. ;  and have amigalibs.res resident in compiler options.
  21.  
  22.  
  23. WBStartup
  24. NoCli
  25. Hostname.s="localhost"  ; "localhost" default destination host address
  26. #PORT=27272             ; 27272 default destination port to send data to
  27. #LOCALPORT=27272        ; 27272
  28. #NO_CONNECTION=1        ; 0 - are we connected, or have we been connected to the Internet since bootup?
  29.                         ;   - 1 for not been connected, 0 for have/are connected.
  30. #DEBUG=1                ; 1 - 1 for debug info and multiple local copies
  31.  
  32. #MAX_NUMBER_PLAYERS=8   ; 8
  33. #MESSAGE_ARRAY_SIZE=100 ; 256
  34. GAME_NAME.s="UDP_Chat"  ; "UDP_Chat"  Game name (for login)
  35. PORT_NAME.s="UDP_Chat"  ; "UDP_Chat"  Rexx portname
  36.  
  37. INCLUDE "Net_Protocol_Header.bb2"  ; Net protocol constants
  38. INCLUDE "UDPHeader.bb2"  ;Standard TCP/UDP library structures
  39.  
  40. DEFTYPE .w
  41.  
  42. max_wait=250       ; Time to wait for an acknowledgement (frames)
  43. number_resends=5   ; Number of resends to wait, before disconnecting player
  44. lag_allowance=5    ; Number of frames to add to the current lag, when waiting for an out-of-order packet.
  45.  
  46. #ACKNOWLEDGE_PACKET=3
  47. #OFFLINE=0
  48. #SERVER=1
  49. #CLIENT=2
  50. packet_number.l=0
  51. online=#OFFLINE
  52. my_number=0
  53. last_message_number.l=0
  54. free_message.l=0
  55. sock.l=-1
  56. security=1   ; level of security warnings (normally 1- show all)
  57. exit=False
  58. game_closing=0
  59.  
  60.  
  61. ResetTimer
  62.  
  63. ;********************************************************
  64.  
  65. NEWTYPE .message_status
  66.   number.l     ; packet number
  67.   ack.w        ; has it been received yet?
  68.   timestamp.l  ; when was it sent?
  69.   message.s    ; message
  70.   resends.w    ; how many times has it been re-sent?
  71.   player       ; which player was it sent too?
  72. End NEWTYPE
  73.  
  74. NEWTYPE .player_info
  75. status.w              ; 0 offline, 1 online
  76. ascii_host_string.s
  77. player_colour.w
  78. score.l
  79. name.s
  80. nick.s
  81. disconnect_requested.w
  82. End NEWTYPE
  83.  
  84. ;*******************************************************
  85. .Dims
  86.  
  87. Dim messages.message_status(#MESSAGE_ARRAY_SIZE)
  88. Dim host.sockaddrin(#MAX_NUMBER_PLAYERS), hostlen.l(#MAX_NUMBER_PLAYERS)
  89. Dim players.player_info(#MAX_NUMBER_PLAYERS),pingprintx.w(#MAX_NUMBER_PLAYERS)
  90. Dim player_honesty(#MAX_NUMBER_PLAYERS,#MAX_NUMBER_PLAYERS)
  91. Dim player_current_lag(#MAX_NUMBER_PLAYERS)
  92.  
  93. DEFTYPE .sockaddrin temphost
  94.  
  95. For a=1 To #MAX_NUMBER_PLAYERS      ; this array dimension is for the player number who is claiming another is offline
  96.   For b=1 To #MAX_NUMBER_PLAYERS    ; this dimension is for the player number who is claimed to be offline
  97.     player_honesty(a,b)=False       ; initialise array
  98.   Next
  99. Next
  100. messages(free_message)\ack=True
  101.  
  102. INCLUDE "UDPFuncs.bb2"  ; basic UDP socket functions
  103.  
  104. ;*******************************************************
  105.  
  106. .Print_String                ; Print a string in window and scroll if necessary
  107. Statement Print_String{text$}
  108.   SHARED ypos
  109.   If ypos<200
  110.     ypos+10
  111.   Else
  112.     WScroll 10,60,590,220,0,10
  113.   EndIf
  114.  
  115.   WLocate 10,ypos
  116.   Print text$               ; print string received
  117. End Statement
  118.  
  119. .Security_Warning
  120. Statement Security_Warning{text$,level}
  121.   SHARED security    ; security= 0 none, 1 all warnings, 2 medium and severe warnings and 3 only severe warnings
  122.   If level>=security  ; only print out security warnings if at set security level or higher
  123.     Print_String{"Warning: " + text$}
  124.   EndIf
  125. End Statement
  126.  
  127. .Get_Packet_Source            ; Check if packet has come from player already logged on.
  128. Function.w Get_Packet_Source{}
  129.  SHARED host(),temphost
  130.  i=0
  131.  Repeat                    ; check for each player (hostname and socket)
  132.    i+1
  133.    If host(i)\sin_addr\s_addr=temphost\sin_addr\s_addr AND  host(i)\sin_port=temphost\sin_port
  134.      exit=1
  135.    EndIf
  136.    If i=8 AND exit=0       ; if at end of players and no match is found
  137.      i=-1
  138.      exit=1
  139.    EndIf
  140.  Until  exit=1
  141.  
  142.  Function Return i
  143. End Function
  144.  
  145. .Get_Ascii_Address                     ; build a.b.c.d numerical address from long number
  146. Function.s Get_Ascii_Address{address.l}
  147.   string_address.l=Inet_NtoA_(address) ; get memory address of ASCII string version of host address (a.b.c.d)
  148.   If string_address=0
  149.     Function Return ""
  150.   EndIf
  151.   Repeat                               ; build ASCII host string
  152.     letter.b=(Peek.b(string_address))
  153.     If letter<>0
  154.       temp$=temp$+Chr$(letter)
  155.     EndIf
  156.     string_address+1
  157.   Until letter=0
  158.   Function Return temp$
  159. End Function
  160.  
  161. .Send_Reliable_Message         ; this message is checked to see if it has arrived, and resent if not
  162. Statement Send_Reliable_Message{send_string.s,player}       ; if no confirmation can be made, link is considered lost
  163.  SHARED messages(),free_message,last_message_number,packet_number.l
  164.  
  165.   send_string.s=Mkl$(packet_number) + send_string.s
  166.   messages(free_message)\number=packet_number,False,Ticks,send_string.s,0,player  ; log message in message array
  167.   If messages(last_message_number)\ack=True
  168.     last_message_number=free_message
  169.   EndIf
  170.  
  171.   WriteUDP{&send_string.s,Len(send_string.s),player}   ; send message
  172.   packet_number+1               ; set packet number to next free packet number (+1)
  173.   free_message+1
  174.   If free_message=#MESSAGE_ARRAY_SIZE+1 Then free_message=0    ; if packet number >#MESSAGE_ARRAY_SIZE then wrap back to 0
  175.  
  176. End Statement
  177.  
  178. .Get_Host_By_Name        ; get a host structure by name (if exists), from a name server
  179. Function Get_Host_By_Name{host$,port.w,player}
  180.   SHARED host(),hostlen()
  181.  
  182.   *a.hostent=gethostbyname_(host$)     ; set up destination address to send packets to
  183.   If *a.hostent=0
  184.     WLocate 10,18
  185.     Print "    No connection to host           "
  186.     Function Return False
  187.   Else
  188.     WLocate 10,18
  189.     Print "Type in data, and hit return to send"
  190.   EndIf
  191.  
  192.   ;Copy Details to our Sockaddrin structure
  193.  
  194.   bb=CopyMem_(*a.hostent\h_addr_list\ItemA,&host(player)\sin_addr,*a.hostent\h_length)
  195.  
  196.   host(player)\sin_port=port       ;Set port number
  197.   host(player)\sin_family=2        ;Set type to AT_INET
  198.   hostlen(player)=SizeOf.sockaddrin        ;Get length of structure sockaddrin
  199.  
  200.   Function Return True
  201. End Function
  202.  
  203. .Get_Host_By_Address      ; get a host structure by address (if exists), from a name server
  204. Function.b Get_Host_By_Address{address.l,port,player}
  205.   SHARED host(),hostlen()
  206.  
  207.   *a.hostent=gethostbyaddr_(address,4,2)  ; check wether host exists- we're not being shammed
  208.  
  209.   If *a.hostent=0
  210.     Function Return False
  211.   EndIf
  212.  
  213.   bb=CopyMem_(*a.hostent\h_addr_list\ItemA,&host(player)\sin_addr,*a.hostent\h_length) ; copy details to player's host
  214.                                                                                        ; newtype to host
  215.   host(player)\sin_port=port               ;Set port number
  216.   host(player)\sin_family=2                ;Set type to AT_INET
  217.   hostlen(player)=SizeOf.sockaddrin        ;Get length of structure sockaddrin
  218.   Function Return True
  219. End Function
  220.  
  221. .Localhost_Name       ; get our internet address- it changes each time we log in to our ISP
  222. Function.s Localhost_Name{}
  223.     If OpenFile (0,"ENV:HOSTNAME")
  224.        FileInput 0
  225.        While NOT Eof(0)
  226.          a$=a$+Inkey$
  227.        Wend
  228.        CloseFile 0
  229.        WindowInput 0
  230.        Function Return a$
  231.     EndIf
  232.     Function Return "localhost"
  233. End Function
  234.  
  235. .Connect_To_Server
  236. Function Connect_to_Server{host.s,port.w}
  237.   SHARED online, CP_REQ_CONNECT.s, GAME_NAME.s, NET_PROTOCOL_VERSION.s
  238.   If online=#OFFLINE
  239.     If Get_Host_By_Name{GTGetString(0,51), GTGetInteger(0,52),1}=True
  240.       Print_String{"Attempting to connect to Server"}
  241.       send$=Mkl$(0) + CP_REQ_CONNECT.s + GAME_NAME.s + Chr$(0) + NET_PROTOCOL_VERSION.s  ; "0000" is a Pad for packet number
  242.       WriteUDP{&send$,Len(send$),1}   ; se